#pragma once
#include<iostream>
#include<functional>
#include <memory>
#include <vector>
#include <unordered_map>
#include <assert.h>

using ReleaseFunc = std::function<void()>;
using TaskFunc=std::function<void()>;
class TimerTask{
    public:
        //TaskFunc本质是提供给外部的函数指针，函数回调，由外部决定执行什么任务
        TimerTask(int id, unsigned int timeout, TaskFunc taskfunc):
            _id(id), _timeout(timeout), _task_func(taskfunc), _canceled(false){}
        ~TimerTask(){
            if(!_canceled){
                _task_func();
            }
            _release_func();
        }
        unsigned int GetTimeout(){
            return _timeout;
        }
        void SetCanceled(bool canceled){
            _canceled=canceled;
        }
        void SetReleaseFunc(ReleaseFunc releasefunc){
            _release_func=releasefunc;
        }
    private:
        int _id;
        unsigned int _timeout;//
        ReleaseFunc _release_func;//删除任务时调用的函数，当析构函数执行时，调用该函数，也就是真正的删除任务
        TaskFunc _task_func;//指定超时后执行的任务
        bool _canceled;//删除任务是否执行
};
class TimerWheel{
    public:
        TimerWheel(int size):wheel_size(size),time(0){
            tasks.resize(size);
        }
        bool TimerAdd(int id, unsigned int timeout,TaskFunc taskfunc){
            std::cout<<"TimerAdd"<<std::endl;
            sharedptr p(new TimerTask(id,timeout,taskfunc));
            if(!p){
                return false;
            }
            //绑定RemoveTask函数，因为RemoveTask是TimerWheel的成员函数，所以需要this指针
            
            p->SetReleaseFunc(std::bind(&TimerWheel::RemoveTask,this,id));
            int pos=(time+timeout)%wheel_size;
            tasks[pos].push_back(p);
            task_map[id]=p;
            return true;
        }
        //刷新时间，因为有消息到来
        bool TimerRefresh(int id){
            std::cout<<"TimerRefresh:"<<id<<std::endl;
            auto it=task_map.find(id);
            if(it==task_map.end()){
                return false;
            }
            auto task=it->second.lock();
            if(!task){
                return false;
            }
            int pos=(time+task->GetTimeout())%wheel_size;//环形数组
            tasks[pos].push_back(task);
            return true;
        }
        //执行任务
        void RemoveTask(int id){
            std::cout<<"RemoveTask"<<id<<std::endl;
            auto it=task_map.find(id);
            if(it==task_map.end()){
                return;
            }
            auto task=it->second.lock();
            if(!task){
                return;
            }
            task_map.erase(it);
        }
        //取消任务
        bool TimerCancel(int id){
            auto it=task_map.find(id);
            if(it==task_map.end()){
                return false;
            }
            auto task=it->second.lock();
            if(!task){
                return false;
            }
            task->SetCanceled(true);
            return true;
        }
        void RunTimerTask(){
            tasks[time].clear();
            time++;
            if(time>=wheel_size){
                time=0;
            }
        }
        void check(){
            for(auto& task:tasks){
                if(!task.empty()){
                    assert(0);
                }
            }
        }
    private:
        int time, wheel_size;
        using weakptr=std::weak_ptr<TimerTask>;//不可以直接用shared_ptr，智能指针计数问题，直接使用无法析构
        using sharedptr=std::shared_ptr<TimerTask>;
        std::vector<std::vector<sharedptr>> tasks;
        std::unordered_map<int,weakptr> task_map;
};